const Ajv = require('ajv')();

module.exports = (app) => {
  const $schema = "http://json-schema.org/draft-07/schema#";
  
  return async (ctx, next) => {
    if (ctx.path.indexOf("/api") < 0) {
      return await next();
    }

    const { body, query, headers } = ctx.request;
    const { params, path, method } = ctx;

    app.logger.info(`[${method}${path}] params: ${JSON.stringify(params)}`);
    app.logger.info(`[${method}${path}] query: ${JSON.stringify(query)}`);
    app.logger.info(`[${method}${path}] body: ${JSON.stringify(body)}`);
    app.logger.info(`[${method}${path}] headers: ${JSON.stringify(headers)}`);
    const schema = app.routerSchema[path]?.[method.toLowerCase()];
    if (!schema) {
      return await next();
    }

    let valid = true;

    let validate;
    
    if (valid && headers && schema.headers) {
      schema.headers.$schema = $schema;
      validate = Ajv.compile(schema.headers);
      valid = validate(headers);
    }
    if (valid && body && schema.body) {
      schema.body.$schema = $schema;
      validate = Ajv.compile(schema.body);
      valid = validate(body);
    }
    if (valid && query && schema.query) {
      schema.query.$schema = $schema;
      validate = Ajv.compile(schema.query);
      valid = validate(query);
    }
    if (valid && params && schema.params) {
      schema.params.$schema = $schema;
      validate = Ajv.compile(schema.params);
      valid = validate(params);
    }
    
    if (!valid) {
      ctx.status = 200;
      ctx.body = {
        success: false,
        code: 442,
        message: `Invalid request parameters : ${validate.errors.map((item) => item.message).join(", ")}`
      };
      return;
    }

    await next();
  };
};
